-- This is part of LazyVim's code, with my modifications.
-- See: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/plugins/formatting.lua

local M = {}

---@param opts ConformOpts
function M.setup(_, opts)
	local Util = require('lazyvim.util')
	for name, formatter in pairs(opts.formatters or {}) do
		if type(formatter) == 'table' then
			---@diagnostic disable-next-line: undefined-field
			if formatter.extra_args then
				---@diagnostic disable-next-line: undefined-field
				formatter.prepend_args = formatter.extra_args
				Util.deprecate(
					('opts.formatters.%s.extra_args'):format(name),
					('opts.formatters.%s.prepend_args'):format(name)
				)
			end
		end
	end

	for _, key in ipairs({ 'format_on_save', 'format_after_save' }) do
		if opts[key] then
			Util.warn(
				("Don't set `opts.%s` for `conform.nvim`,\nit is configured automatically."):format(
					key
				)
			)
			opts[key] = nil
		end
	end
	require('conform').setup(opts)
end

return {
	{
		'stevearc/conform.nvim',
		dependencies = { 'mason.nvim' },
		lazy = true,
		cmd = 'ConformInfo',
		keys = {
			{
				'<leader>cF',
				function()
					require('conform').format({ formatters = { 'injected' } })
				end,
				mode = { 'n', 'v' },
				desc = 'Format Injected Langs',
			},
		},
		init = function()
			-- Install the conform formatter on VeryLazy
			local Util = require('lazyvim.util')
			Util.on_very_lazy(function()
				Util.format.register({
					name = 'conform.nvim',
					priority = 100,
					primary = true,
					format = function(buf)
						local plugin = require('lazy.core.config').plugins['conform.nvim']
						local Plugin = require('lazy.core.plugin')
						local opts = Plugin.values(plugin, 'opts', false)
						require('conform').format(Util.merge(opts.format, { bufnr = buf }))
					end,
					sources = function(buf)
						local ret = require('conform').list_formatters(buf)
						---@param v conform.FormatterInfo
						return vim.tbl_map(function(v)
							return v.name
						end, ret)
					end,
				})
			end)
		end,
		opts = function()
			local plugin = require('lazy.core.config').plugins['conform.nvim']
			if plugin.config ~= M.setup then
				require('lazyvim.util').error({
					"Don't set `plugin.config` for `conform.nvim`.\n",
					'This will break formatting.',
				}, { title = 'Formatter' })
			end
			---@class ConformOpts
			local opts = {
				-- Use these options when formatting with the conform.nvim formatter
				format = {
					timeout_ms = 3000,
					async = false, -- not recommended to change
					quiet = false, -- not recommended to change
				},
				---@type table<string, conform.FormatterUnit[]>
				formatters_by_ft = {
					lua = { 'stylua' },
					fish = { 'fish_indent' },
					sh = { 'shfmt' },
				},
				-- The options you set here will be merged with the builtin formatters.
				-- You can also define any custom formatters here.
				---@type table<string, conform.FormatterConfigOverride|fun(bufnr: integer): nil|conform.FormatterConfigOverride>
				formatters = {
					injected = { options = { ignore_errors = true } },
					-- # Example of using dprint only when a dprint.json file is present
					-- dprint = {
					--   condition = function(ctx)
					--     return vim.fs.find({ "dprint.json" }, { path = ctx.filename, upward = true })[1]
					--   end,
					-- },
					--
					-- # Example of using shfmt with extra args
					-- shfmt = {
					--   prepend_args = { "-i", "2", "-ci" },
					-- },
				},
			}
			return opts
		end,
		config = M.setup,
	},
}
